﻿namespace CV.Controllers.Test.Mvc
{
    using CV.Controllers.Mvc;
    using CV.Controllers.Test.MvcFakes;
    using CV.Entities.Dto;
    using CV.Entities.Models;
    using CV.Interfaces.Bll;
    using CV.Interfaces.Tools;
    using CV.Resources.Controller;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;
    using System;
    using System.Web.Mvc;

    [TestClass]
    public class LoginControllerTest
    {
        private static readonly IFormsAuthenticationWrapper formAuth = new FakeFormsAuthenticationWrapper();
        private static readonly IMembershipWrapper membership = new FakeMembershipWrapper();
        private static readonly IUserService userService;

        static LoginControllerTest()
        {
            var mock = new Mock<IUserService>();
            mock.Setup(service => service.Create(It.IsAny<User>()))
                .Returns<User>(x =>
                {
                    x.Id = Guid.NewGuid();
                    return x;
                });
            userService = mock.Object;
        }

        public static LoginController GetController()
        {
            var controller = new LoginController(userService, formAuth, membership);
            controller.ControllerContext = new FakeControllerContext(controller);
            return controller;
        }

        [TestMethod]
        public void Index_Has_Model()
        {
            var ctrl = GetController();
            var result = ctrl.Index() as ViewResult;

            Assert.IsNotNull(result.Model, "No model provided");
        }

        [TestMethod]
        public void Logout_Redirect_To_Index()
        {
            var ctrl = GetController();
            var result = ctrl.Logout() as RedirectToRouteResult;

            Assert.AreEqual("Index", result.RouteValues["action"], "The action is wrong");
        }

        [TestMethod]
        public void Signup_Has_Model()
        {
            var ctrl = GetController();
            var result = ctrl.Signup() as ViewResult;

            Assert.IsNotNull(result.Model, "No model provided");
        }

        [TestMethod]
        public void Signup_CreationSuccessfull()
        {
            var ctrl = GetController();

            var model = new SignupModel()
            {
                DateOfBirth = DateTime.Today,
                FirstName = "FirstName",
                LastName = "LastName",
                Login = "Login",
                Password = "Password",
            };

            var result = ctrl.Signup(model) as RedirectToRouteResult;

            Assert.IsNotNull(ctrl.TempData["newLogin"]);
            Assert.AreEqual("Index", result.RouteValues["action"]);
        }

        [TestMethod]
        public void Login_Successfull()
        {
            var ctrl = GetController();
            var result = ctrl.Index(new LoginModel() { Login = "Joe" }) as RedirectToRouteResult;

            Assert.AreEqual("Index", result.RouteValues["action"], "The action is wrong");
            Assert.AreEqual("Home", result.RouteValues["controller"], "The controller is wrong");
        }

        [TestMethod]
        public void Login_Failed()
        {
            var ctrl = GetController();
            var result = ctrl.Index(new LoginModel() { Login = "Joey" }) as ViewResult;

            var model = result.Model as LoginModel;

            Assert.IsNotNull(model, "A model is expected");
            Assert.AreEqual(Login.Invalid, model.ErrorMessage);
        }
    }
}
